﻿#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <vector>
#include <list>
#include <assert.h>
#include <algorithm>
#include <functional>
#include <map>
using namespace std;
#include "list.h"
// 1.统一的列表初始化
class Date
{
public:
	Date(int year, int month, int day)
		:_year(year)
		,_month(month)
		,_day(day)
	{
		cout << "Date(int year, int month, int day) ~构造" << endl;
	}
	Date(const Date& d1)
	{
		cout << "Date(const Date& d1)" << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
struct Point
{
	int _x;
	int _y;
};
int main()
{
	Date d1(2025, 1, 1);       // 直接构造
	Date d2 = { 2025, 5, 5 };   // 这里是构造 + 拷贝构造->优化为直接构造

	Date d3(d1);
	Date* p1 = new Date[3]{ d1, d2, d2 };
	Date* p2 = new Date[3]{ {2025, 4, 4}, d2, d2};

	int a[] = { 1, 2, 3, 4 };
	int b{ 4 };                // 内置类型

	Point t{ 1, 2 };   // Point t = { 1, 2 };也可以
	cout << t._x << " " << t._y << endl;
 
	return 0;
}
// 2.initializer_list
int main()
{
	auto t = { 1, 2, 4 };
	cout << typeid(t).name() << endl;
	initializer_list<int> it = { 1, 5, 6, 7, 8 };
	for (auto e : it)
	{
		cout << e << " ";
	}
	return  0;
}

// 3.auto
int main()
{
	vector<int> vc;
	// vector<int>::iterator it = vc.begin();
	auto it = vc.begin();     // auto省略写类型
	return 0;
}

// 4.decltype
int main()
{
	int i = 1;
	double j = 1.1;
	auto ret = i * j;

	// vector的元素的类型是ret，使用decltype获取
	vector<decltype(ret)> vc;
	vc.push_back(1);
	vc.push_back(2.3);
	for (auto e : vc)
	{
		cout << e << " ";
	}
	return 0;
}

 //5.右值引用和移动语义
 //左值引用和右值引用
 //左值：我们可以获取它的地址 + 可以对它赋
 //值，左值可以出现赋值符号的左边，右值不能出现在赋值符号左边

int main()
{
	// 以下的p、b、c、*p都是左值
	int* p = new int(0);
	int b = 1;
	const int c = 2;
	// 以下几个是对上面左值的左值引用

	int*& rp = p;
	int& rb = b;
	const int& rc = c;
	int& pvalue = *p;

	return 0;
}

//字面常量、表达式返回值，函数返回值(这个不能是左值引
//用返回)等等，右值可以出现在赋值符号的右边，但是不能出现出现在赋值符号的左边，右值不能
//取地址。右值引用就是对右值的引用，给右值取别名。
int main()
{
	int i = 0;
	int j = i;

	10;   // 字面常量
	i + j;  // 表达式的返回值
	fmin(i, j);

	// 这三个都是右值引用
	int&& r1 = 10;
	int&& r2 = i + j;
	int&& r3 = fmin(i, j);

	// 左值引用可以给右值取别名吗? 不能，但是const左值引用可以
	int& r4 = 10;        // 错误，权限放大了
	const int& r4 = 10;

	// 右值引用可以给左值取别名吗？ 不能，但是右值引用可以对move(左值)取别名
	int&& r5 = i;  // 错误
	int&& r5 = move(i);
	return 0;
}

// 6.右值引用使用场景和意义
namespace bit
{
	class string
	{
	public:
		typedef char* iterator;
		iterator begin()
		{
			return _str;
		}
		iterator end()
		{
			return _str + _size;
		}
		string(const char* str = "")
			:_size(strlen(str))
			, _capacity(_size)
		{
			cout << "string(char* str) -- 构造" << endl;
			_str = new char[_capacity + 1];
			strcpy(_str, str);
		}

		 s1.swap(s2)
		void swap(string& s)
		{
			::swap(_str, s._str);
			::swap(_size, s._size);
			::swap(_capacity, s._capacity);
		}

		// 拷贝构造
		string(const string& s)
			:_str(nullptr)
		{
			cout << "string(const string& s) -- 深拷贝" << endl;
			string tmp(s._str);
			swap(tmp);
		}

		// 赋值重载
		string& operator=(const string& s)
		{
			cout << "string& operator=(string s) -- 深拷贝" << endl;
			/*string tmp(s);
			swap(tmp);*/
			if (this != &s)
			{
				char* tmp = new char[s._capacity + 1];
				strcpy(tmp, s._str);
				delete[] _str;

				_str = tmp;
				_size = s._size;
				_capacity = s._capacity;
			}
			return *this;
		}

		string(string&& s)
		{
			cout << "string(string&& s) -- 移动拷贝" << endl;
			swap(s);
		}

		string& operator=(string&& s)
		{
			cout << " string& operator=(string&& s) -- 移动赋值" << endl;
			swap(s);
			return *this;
		}

		~string()
		{
			delete[] _str;
			_str = nullptr;
		}
		char& operator[](size_t pos)
		{
			assert(pos < _size);
			return _str[pos];
		}
		void reserve(size_t n)
		{
			if (n > _capacity)
			{
				char* tmp = new char[n + 1];
				strcpy(tmp, _str);
				delete[] _str;
				_str = tmp;
				_capacity = n;
			}
		}
		void push_back(char ch)
		{
			if (_size >= _capacity)
			{
				size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;
				reserve(newcapacity);
			}
			_str[_size] = ch;
			++_size;
			_str[_size] = '\0';
		}

		//string operator+=(char ch)
		string& operator+=(char ch)
		{
			push_back(ch);
			return *this;
		}
		const char* c_str() const
		{
			return _str;
		}

	private:
		char* _str = nullptr;
		size_t _size = 0;
		size_t _capacity = 0; // 不包含最后做标识的\0
	};

	string to_string(int x)
	{
		string tmp;
		while (x)
		{
			int val = x % 10;
			x /= 10;
			tmp += ('0' + val);
		}
		reverse(tmp.begin(), tmp.end());
		return tmp;
	}
}
int main()
{
	bit::string s;
	s = bit::to_string(111);
	bit::string s1("111");
	bit::string s2(s1);
	move(s1);
	bit::string s3 = s1;
	return 0;
}
int main()
{
	csj::list<bit::string> lt;       // 初始化的时候会调用深拷贝
	bit::string s1("hello world");
	lt.push_back(s1);                // 左值引用这是深拷贝

	lt.push_back(bit::to_string(1234));  // bit::to_string(1234) 是移动拷贝
	lt.push_back("11111");
	return 0;
}

// 7.完美转发
void Fun(int& x) { cout << "左值引用" << endl; }
void Fun(const int& x) { cout << "const 左值引用" << endl; }
void Fun(int&& x) { cout << "右值引用" << endl; }
void Fun(const int&& x) { cout << "const 右值引用" << endl; }
// 模板中的&&不代表右值引用，而是万能引用，其既能接收左值又能接收右值。
// 模板的万能引用只是提供了能够接收同时接收左值引用和右值引用的能力，
// 但是引用类型的唯一作用就是限制了接收的类型，后续使用中都退化成了左值，
// 我们希望能够在传递过程中保持它的左值或者右值的属性, 就需要用我们下面学习的完美转发
// 函数模版：万能引用
template<typename T>
void PerfectForward(T&& t)
{
	// forward<T>让t的属性保留
	Fun(forward<T>(t));
}
int main()
{
	PerfectForward(10);        // 右值
	int a;
	PerfectForward(a);         // 左值
	PerfectForward(std::move(a));   // 右值
	const int b = 8;
	PerfectForward(b);              // const 左值
	PerfectForward(std::move(b));   // const 右值
	return 0;
}

// 8.强制生成默认成员函数关键字default和禁止生成delete
class Person
{
public:
	Person(const char* name = "", int age = 0)
		:_name(name)
		, _age(age)
	{}

	Person(const Person& p)
	:_name(p._name)
	,_age(p._age)
	{}

	Person(Person&& p) = default;     
	// 上面写了拷贝构造，所以编译器不会默认生成移动拷贝，所以我们使用关键字default强制生成
	/*Person& operator=(const Person& p)
	{
		if(this != &p)
		{
		_name = p._name;
		_age = p._age;
		}
		return *this;
	}*/

	/*~Person()
	{}*/
private:
	bit::string _name;
	int _age;
};
int main()
{
	Person s1;
	Person s2 = s1;
	Person s3 = std::move(s1);
	return 0;
}

// 9.可变参数模板
// Args是一个模板参数包，args是一个函数形参参数包
// 声明一个参数包Args...args，这个参数包中可以包含0到任意个模板参数.
void _ShowList()
{
	cout << endl;
}
template <class T, class ...Args>
void _ShowList(const T& val, Args... args)
{
	cout << val << " ";
	_ShowList(args... );
}
template <class ...Args>
void ShowList(Args... args)
{
	_ShowList(args... );
}

int main()
{
	ShowList(1);
	ShowList(1, 2.2);
	ShowList(1, 2.2, 5);
	return 0;
}


template <class T>
int PrintArg(T t)
{
	cout << t << " ";
	return 0;
}
//展开函数
template <class ...Args>
void ShowList(Args... args)
{
	int arr[] = { (PrintArg(args))... };
	cout << endl;
}
int main()
{
	ShowList(1);
	ShowList(1, 'A');
	ShowList(1, 'A', std::string("sort"));
	return 0;
}

int main()
{
	std::list<bit::string> lt;
	bit::string s1("1111");
	lt.push_back(s1);
	lt.push_back(move(s1));    // 这里的s1已经变成空了

	
	cout << endl;
	bit::string s2("1111");
	lt.emplace_back(s2);
	lt.emplace_back(move(s2));
	
	cout << endl;

	lt.push_back("2222");
	lt.emplace_back("2222");

	return 0;
}

// 10.lambda表达式

struct Goods
{
	string _name;  // 名字
	double _price; // 价格
	int _evaluate; // 评价
	Goods(const char* str, double price, int evaluate)
		:_name(str)
		, _price(price)
		, _evaluate(evaluate)
	{}
};
struct ComparePriceLess   // 升序
{
	bool operator()(const Goods& g1, const Goods& g2)
	{
		return g1._price < g2._price;
	}
};

struct ComparePriceGreater
{
	bool operator()(const Goods& g1, const Goods& g2)
	{
		return g1._price > g2._price;
	}
};
int main()
{
	vector<Goods> v = { { "苹果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2,
3 }, { "菠萝", 1.5, 4 } };
	//sort(v.begin(), v.end(), ComparePriceLess());
	//sort(v.begin(), v.end(), ComparePriceGreater());

	sort(v.begin(), v.end(), [](const Goods g1, const Goods g2) {return g1._evaluate > g2._evaluate; });


	auto f1 = [](int x) {cout << x << endl; return 0; };
	f1(1);
	cout << typeid(f1).name() << endl;

	return 0;
}

int main()
{
	int x = 1;
	int y = 2;
	auto f1 = [](int& x, int& y)  {int tmp = x; x = y; y = tmp; };
	f1(x, y);
	cout << x << " " << y << endl;
	cout << &x << " " << &y << endl;

	auto f2 = [&x, &y]() {
		cout << &x << " " << &y << endl;
		int tmp = x; x = y; y = tmp; 
	};  // 传引用捕捉
	f2();
	cout << x << " " << y << endl;


	return 0;
}

// 11.包装器
struct Swap
{
	void operator()(int& r1, int& r2)
	{
		int tmp = r1;
		r1 = r2;
		r2 = tmp;
	}
};
void funcSwap(int& r1, int& r2)
{
	int tmp = r1;
	r1 = r2;
	r2 = tmp;
}

int main()
{
	auto swaplambda = [](int& x, int& y) {int tmp = x; x = y; y = tmp; };
	map<string, function<void(int&, int&)>> mp = { 
		{"仿函数",Swap()}, 
		{"普通函数",funcSwap}, 
		{"lambda", swaplambda}};
	int x = 1;
	int y = 2;

	mp["仿函数"](x, y);
	cout << x << " " << y << endl;

	mp["普通函数"](x, y);
	cout << x << " " << y << endl;

	mp["lambda"](x, y);
	cout << x << " " << y << endl;

	return 0;
}

struct pos
{
	double sub(double x, double y)
	{
		return x - y;
	}
};

int main()
{
	// 成员函数取地址，比较特殊，需要加&和类域 
	function<double(pos*, double, double)> f1 = &pos::sub;
	pos p1;
	cout << f1(&p1, 1.1, 2.2) << endl;

	function<double(double, double)> f2 = bind(&pos::sub, pos(), placeholders::_2, placeholders::_1);
	cout << f2(4.4, 2.2) << endl;
	return 0;
}
